/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */



package ia1_othello;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author jonathan
 */
public class Minimax {
    int[][] tab = new int[8][8];
    int[][] tableroPesos = new int[8][8];
    nodo nodoActual;
    static int VACIO = 0;
    static int BLANCO = 1;
    static int NEGRO = 2;
    boolean finjuego = false;
    nodo raiz;
    boolean pasaTurno = false;
    
    ArrayList<int[]> tirosValidos = new ArrayList();
    
    int PosXin = -1;
    int PosYin = -1;
    
    public Minimax(){
        for (int i=0;i<8;i++){
            for(int j=0; j<8; j++){
                tab[i][j] = 0;
            }            
        }
        tab[3][3]=BLANCO; //blanco
        tab[3][4]=NEGRO;  //negro
        tab[4][3]=NEGRO;
        tab[4][4]=BLANCO;
        /*****ADICIONALES DE PRUEBA***/
        tab[0][1]=NEGRO;
        tab[0][2]=NEGRO;
        tab[0][3]=NEGRO;
        tab[1][1]=NEGRO;
        tab[1][3]=NEGRO;
        tab[1][5]=NEGRO;
        tab[2][2]=NEGRO;
        tab[2][4]=NEGRO;
        tab[3][2]=NEGRO;
        tab[4][2]=NEGRO;
        
        tab[1][2]=BLANCO;
        tab[2][3]=BLANCO;
        tab[3][3]=BLANCO;
        tab[3][4]=BLANCO;
        this.setValoresPosicion();
    }
    
    public boolean verificarPosicion(int x,int y){ //verifica que la posicion este vacia
        try{
            if(tab[x][y]== VACIO)return true;
        }catch(Exception e){            
        }
        return false;
    }
    
    public void setValoresPosicion(){ //coloca los pesos para la matriz
        tableroPesos[0][0] = 120;
        tableroPesos[0][1] = -20;
        tableroPesos[0][2] = 20;
        tableroPesos[0][3] = 5;
        tableroPesos[1][0] = -20;
        tableroPesos[1][1] = -40;
        tableroPesos[1][2] = -5;
        tableroPesos[1][3] = -5;
        tableroPesos[2][0] = 20;
        tableroPesos[2][1] = -5;
        tableroPesos[2][2] = 15;
        tableroPesos[2][3] = 3;
        tableroPesos[3][0] = 5;
        tableroPesos[3][1] = -5;
        tableroPesos[3][2] = 3;
        tableroPesos[3][3] = 3;
        
        for(int i=0; i<4; i++){
            for(int j=0; j<4; j++){
                tableroPesos[i+4][j] = tableroPesos[3-i][j];  //subcuadro superior derecho
                tableroPesos[i][j+4] = tableroPesos[i][3-j];  //subcuadro inferior izquierdo
                tableroPesos[i+4][j+4] = tableroPesos[3-i][3-j];  //subcuadro inferior derecho                
            }
        }
        System.out.println("Matriz de pesos por posicion");
        imprimirMatriz(tableroPesos); 
        
    }
    
    public void imprimirMatriz(int[][] mat){
        System.out.print(" ");
        for(int j=0; j<8; j++){
                System.out.print(" "+j+" ");
            }
        System.out.print("\n");
        for(int i=0; i<8; i++){
            System.out.print(i);            
            for(int j=0; j<8; j++){
                System.out.print(" "+mat[i][j]+" ");
            }
            System.out.print("\n");
        } 
    }
        
    public void jugar() {
        while (!finjuego) {

            System.out.println();
            imprimirMatriz(tab);
            /**** obtener tiros validos para jugador humano********/
            obtenerTirosValidos(1);
            System.out.println("/***************Juega Persona********/");
            System.out.println("Tiros validos:: " + this.tirosValidos.size());
            mostrarvalidos();
            if(tirosValidos.isEmpty()){
                if(pasaTurno){
                    finjuego = true;
                    System.out.println("No hay mas movimientos, termina el juego");
                }else{
                    System.out.println("Pasa el turno, no hay tiros validos");
                    pasaTurno = true;
                }                
            }else pedirPosicionTiro();                            
            
            imprimirMatriz(tab);
            TiroComputadora();
            //imprimirMatriz(tab);
        }
        mostrarGanador();
    }
    
    public void TiroComputadora(){
        this.tirosValidos.clear();
        obtenerTirosValidos(2);
        System.out.println("/***************Juega Computadora********/");
        System.out.println("Tiros validos:: "+this.tirosValidos.size());
        mostrarvalidos();
        if(tirosValidos.isEmpty()){
                if(pasaTurno){
                    finjuego = true;
                    System.out.println("No hay mas movimientos, termina el juego");
                }else{
                    System.out.println("Pasa el turno, no hay tiros validos");
                    pasaTurno = true;
                }                
            }else iniciarAlgoritmo();        
    }
    
    public void mostrarvalidos(){
     int[] coor = new int[2];
    Iterator it = this.tirosValidos.iterator();
    while(it.hasNext()){
        coor= (int[]) it.next();
        System.out.println("posy:: "+coor[0]+" posx:: "+coor[1]);
    }
    }
    
    public void obtenerTirosValidos(int jugador){
            
        boolean Nocambiar = false;
        
            for (int zi =0; zi < 8; zi++)
            {
                
                for (int zj = 0; zj < 8; zj++)
                {
                    if (tab[zi][zj]== 0) {
                        ObtenerTirosValidos(zj, zi, jugador,Nocambiar);
                    }
                    
                }
            }
        
    }
    
    
    public void pedirPosicionTiro(){
        pasaTurno = false;
        boolean tirovalido=false;
        
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while(!tirovalido){
        try {
            
            System.out.print("Ingrese Fila: ");
            String cad;
            cad = in.readLine();
            this.PosYin= Integer.valueOf(cad);
            cad=null;
            System.out.print("Ingrese Columna: ");            
            cad = in.readLine();            
            this.PosXin= Integer.valueOf(cad);            
        } catch (IOException ex) {
            Logger.getLogger(IA1_othello.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        System.out.println("fila: "+PosYin+" columna: "+PosXin);
        tirovalido = validarTiro(PosXin,PosYin,1);
        if (!tirovalido){
           System.out.println("Tiro NO valido ingrese otra poscion!!!!");
        }
        }
        /***********Se tiene el tiro valido entonces se cambian las fichas en el tablero*************/
        this.flanquear_direcciones(PosXin, PosYin, 1, true);        
    }
    
    public void ObtenerTirosValidos(int px, int py, int jug,boolean cambiar){
        boolean valido=false;
        if ( ((px>=0 )&& (px < 8)) && ((py>=0) && (py<8) ) ){
            flanquear_direcciones(px,py,jug,cambiar);
            valido = true;            
        }        
    }
    
    public void flanquear_direcciones(int px, int py,int jug, boolean cambiar){
            verificar_izq_der(px,py,jug,cambiar);
            verificar_der_izq(px,py,jug,cambiar);
            verificar_sur_norte(px,py,jug,cambiar);
            verificar_norte_sur(px,py,jug,cambiar);
         
            verificar_izq_der_arriba_abajo(px,py,jug,cambiar);
            verificar_der_izq_arriba_abajo(px,py,jug,cambiar);
            verificar_der_izq_abajo_arriba(px,py,jug,cambiar);
            verificar_izq_der_abajo_arriba(px,py,jug,cambiar);
    }
    
    public void verificar_norte_sur(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy < 7) {
            tempy++;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy < 7) {
                tempy++;
            }else if (tempy == 7){
                break;
            }
        }
        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            for (int i = py; i < tempy; i++) {
                tab[i][px] = jug;
            }
        }

    }
    
    public void verificar_izq_der(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempx < 7) {
            tempx++;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempx < 7) {
                tempx++;
            }else if (tempx == 7){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            for (int i = px; i < tempx; i++) {
                tab[py][i] = jug;
            }
        }

    } 
    
    public void verificar_der_izq(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempx > 0) {
            tempx--;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempx > 0) {
                tempx--;
            }else if (tempx == 0){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            for (int i = px; i > tempx; i--) {
                tab[py][i] = jug;
            }
        }

    }
    
    public void verificar_sur_norte(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy > 0) {
            tempy--;
        }

        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy > 0) {
                tempy--;    
            }else if (tempy == 0){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            for (int i = py; i > tempy; i--) {
                tab[i][px] = jug;
            }
        }

    }
    
    public void verificar_izq_der_arriba_abajo(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy < 7) {
            tempy++;
        }
        if (tempx < 7) {
            tempx++;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy < 7) {
                tempy++;
            }else if (tempy == 7){
                break;
            }
            
            
            if (tempx < 7) {
                tempx++;
            }else if (tempx == 7){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            int j = px;
            for (int i = py; i < tempy; i++) {
                tab[i][j] = jug;
                j++;
            }
        }

    }
    
    public void verificar_der_izq_arriba_abajo(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy < 7) {
            tempy++;
        }
        if (tempx > 0) {
            tempx--;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy < 7) {
                tempy++;
            }else if (tempy == 7){
                break;
            }
            
            
            if (tempx > 0) {
                tempx--;
            }else if (tempx == 0){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            int j = px;
            for (int i = py; i < tempy; i++) {
                tab[i][j] = jug;
                j--;
            }
        }

    }
    
    public void verificar_der_izq_abajo_arriba(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy > 0) {
            tempy--;
        }
        if (tempx > 0) {
            tempx--;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy > 0) {
                tempy--;
            }else if (tempy == 0){
                break;
            }
            if (tempx > 0) {
                tempx--;
            }else if (tempx == 0){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            int j = px;
            for (int i = py; i > tempy; i--) {
                tab[i][j] = jug;
                j--;
            }
        }

    }
    
    public void verificar_izq_der_abajo_arriba(int px, int py, int jug, boolean cambiar) {
        int cont = 0;
        int tempx = 0;
        int tempy = 0;
        tempy = py;
        tempx = px;
        int ficha = 0;
        if (jug == 1) {
            ficha = 2;
        } else {
            ficha = 1;
        }
        if (tempy > 0) {
            tempy--;
        }
        if (tempx < 7) {
            tempx++;
        }
        while (tab[tempy][tempx] == ficha) {
            cont++;
            if (tempy > 0) {
                tempy--;
            }else if (tempy == 0){
                break;
            }
            
            if (tempx < 7) {
                tempx++;
            }else if (tempx == 7){
                break;
            }
        }

        if (!cambiar) {
            if (tab[tempy][tempx] == jug && cont > 0) {
                int[] tempCoor = new int[2];
                tempCoor[0] = py;
                tempCoor[1] = px;
                tirosValidos.add(tempCoor);
            }
        } else if (tab[tempy][tempx] == jug && cont > 0) {
            int j = px;
            for (int i = py; i > tempy; i--) {
                tab[i][j] = jug;
                j++;
            }
        }

    }
    
    public boolean validarTiro(int px,int py, int jug){
    boolean valido=false;
    int[] coor = new int[2];
    Iterator it = this.tirosValidos.iterator();
    while(it.hasNext()&&!valido){
        coor= (int[]) it.next();
        if ((coor[0]==py)&&(coor[1]==px)){
            valido=true;
        }
    }
    return valido;
    }
    
    
    public void iniciarAlgoritmo(){
        pasaTurno = false;
        raiz= new nodo();
        raiz.setTablero(tab);        
        
        raiz.setPadre(null);
        raiz.setNumero_nodo(0);        
        raiz.setVal(0);
        
        nodoActual=raiz;
    //    expandirNodo(raiz);     
        
        generarHijos();
        this.seleccionarMejor();
    }
    
    public void generarHijos(){
        int[][] temp = new int[8][8];
        temp = tab;
        for(int i=0; i<this.tirosValidos.size(); i++){
            int[] coor = new int[2];
            coor= (int[])tirosValidos.get(i);
            
            //this.flanquear_direcciones(coor[1], coor[0], 2, false); 
            nodo n = new nodo();
            n.setTablero(tab);
            n.setVal(this.tableroPesos[coor[1]][coor[0]]);            
            tab = temp; //lo coloco como estaba al inicio
            //imprimirMatriz(tab);
            //System.out.println("**********");
            n.setPadre(raiz);
            raiz.addHijo(n);
        }            
    }
    
    public int[][] seleccionarMejor(){
        nodo mejorNodo = null;
        int mejor = 0;
        for(int i=0; i<raiz.numHijos(); i++){
            //System.out.println("Val. "+ raiz.getHijo(i).getVal());
            if(mejorNodo == null)mejorNodo = raiz.getHijo(i);
            else{
                if(raiz.getHijo(i).getVal() > mejorNodo.getVal()){
                    mejorNodo = raiz.getHijo(i);
                    mejor = i;
                }
            }
        }
        int[] coor = new int[2];
        coor= (int[])tirosValidos.get(mejor); 
        System.out.println("Seleccionada posicion: "+coor[0]+","+coor[1]);
        this.flanquear_direcciones(coor[1], coor[0], 2, true);
        return tab;
        //System.out.println("Mejor val."+ mejorNodo.getVal());
        //imprimirMatriz(mejorNodo.getTablero());
        //System.out.println(mejorNodo.toString());
        //if(mejorNodo == null)return tab;
        //return mejorNodo.getTablero();
    }
    
    public void mostrarGanador(){
        int cantJug = 0;
        int cantPC = 0;
        
        for(int i=0; i<8; i++){
            for(int j=0; j<8; j++){
                if(tab[i][j] == 1)cantJug++;
                else if(tab[i][j] == 2)cantPC++;
            }
        }
        
        System.out.println("Fichas Jugador 1: "+ cantJug);        
        System.out.println("Fichas Computadora: "+ cantPC);
        
        if(cantJug>cantPC)System.out.println("GANADOR!!: Jugador 1");
        else System.out.println("GANADOR!!: computadora");
    }
    
    public void colocarFicha(int x, int y, int jugador){
        if(jugador == 1)tab[x][y] = BLANCO;
        
        for(int i=0; i<x; i++){
            
        }
        
        flanquear();
    }
    
    public void flanquear(){
        
    }
    
/*    public void expandirNodo(nodo nodoExpa){
    
        for(int i=0;i<4;i++){
            int nmov = nodoExpa.PosBlanco+movimientos[i];
          if (this.validar_mov(i, nmov)){
              this.AgregarNodo(nodoExpa, nmov);
          }            
        }
        
    }
    
    public void AgregarNodo(nodo n, int sig_pos){
        
        int[]tempPuzzle = new int[9];       
        
        for (int i=0;i<9;i++){
            tempPuzzle[i] = n.getpuzzle()[i];
        }
        int tempBlanco = (int) n.getBlanco();
        int val_sigPos = tempPuzzle[sig_pos];
        tempPuzzle[tempBlanco] = val_sigPos;
        tempPuzzle[sig_pos] = 0;
        tempBlanco = sig_pos;        
        
        // creo el nuevo nodo 
        nodo nuevoNodo = new nodo();  
        
        nuevoNodo.setBlanco(tempBlanco);
        
        int np = 0; 
        np = n.getnumero();
        
        this.Total_Nodos++;
        nuevoNodo.setnumero(this.Total_Nodos);
        nuevoNodo.setpadre(np);
        nuevoNodo.setpuzzle(tempPuzzle);        
        nuevoNodo.setvalg(n.getvalg()+1);
        
        if (this.tipoSolucion==1){
            nuevoNodo.setManhatan(this.cacularManhatan(tempPuzzle));
            nuevoNodo.setvalf(nuevoNodo.getvalg()+nuevoNodo.getManhatan());
        }else if (this.tipoSolucion==2){
            nuevoNodo.setPosicion(this.calcularPorPosicion(tempPuzzle));
            nuevoNodo.setvalf(nuevoNodo.getvalg()+nuevoNodo.getPosicion());
        }
        this.abierta.add(nuevoNodo);
    }
   */ 
}


